<?php

namespace App\Models\User\Repositories;

use App\Models\User\WechatOfficialUser;
use App\Trip\Repository\BaseRepository;
use Exception;
use Illuminate\Support\Facades\Cache;
use JetBrains\PhpStorm\Pure;

class WechatOfficialUserRepository extends BaseRepository implements Interfaces\WechatOfficialUserRepositoryInterface
{
    #[Pure] public function __construct(WechatOfficialUser $model)
    {
        parent::__construct($model);
    }

    /**
     * @throws Exception
     */
    public function addData(array $data): WechatOfficialUser
    {
        if ($info = $this->findByOpenId($data['openid'])) {
            if ($info->getUserId() != $data['user_id']) {
                throw new Exception("ERROR");
            }
            if (!$info->getAppId()) {
                $this->updateData($info, $data);
            }
            return $info;
        }
        return $this->create($data);
    }

    public function findByOpenId(string $openid): ?WechatOfficialUser
    {
        $cache_key = "OfficialUser:oid:{$openid}";
        if (Cache::has($cache_key)) {
            $info = Cache::get($cache_key);
        } else {
            $info = $this->findOneBy([
                'openid' => $openid,
            ]);
            $info && Cache::put($cache_key, $info, config('trip.ttl.day'));
        }
        return $info;
    }

    public function updateData(WechatOfficialUser $appUser, array $data): bool
    {
        return $this->update($data, $appUser);
    }

    public function findByAppIdAndUserId(string $user_id, string $appid = ''): ?WechatOfficialUser
    {
        $cache_key = "OfficialUser:uid:{$user_id}:aid:{$appid}";
        if (Cache::has($cache_key)) {
            $info = Cache::get($cache_key);
        } else {
            $w = [
                'user_id' => $user_id,
            ];
            if ($appid) {
                $w['appid'] = $appid;
            }
            $info = $this->findOneBy($w);
            $info && Cache::put($cache_key, $info, config('trip.ttl.day'));
        }
        return $info ? $this->findByOpenId($info->getOpenId()) : null;
    }
}